---@class RedRob.Buffer:RedRob.BuffBase
---@field New fun():RedRob.Buffer
local Buffer = RedRob.CreateClass("Buffer","BuffBase")

local STAGE = {
    start = 1,      --开始阶段
    loop = 2,     --循环阶段
    destroying= 3,  --销毁阶段
}
function Buffer:OnCreate()
    RedRob.BuffBase.OnCreate(self)
    self.cfg = nil
    self.showCfg = nil
    self.stateList = {}
    ---@type GameObject
    self.gameObject = nil
    ---@type Spine.Unity.SkeletonAnimation
    self.animation = nil
    ---@type MeshRenderer
    self.render = nil
    self.offSet = Vector3.GetCacheVec()
    self.pos =  Vector3.GetCacheVec()
    self.resName = ""
    self.LoadRequestId = 0
    if self.stageData then
        self.stageData.stage = 0
        self.stageData.maxTime = 0
    else
        self.stageData = {stage = 0,countDown = false,time = 0,maxTime = 0,isExecute = false,isLoop = false}
    end

    self.isDestroyed = false
    self.isDie = false
    self.isLoading = false
end

function Buffer:OnDestroy()
    self.isDestroyed = true
    RedRob.PoolMgr.CancelLoad(self.LoadRequestId)
    RedRob.PoolMgr.ReturnPrefabToPool(self.resName,self.gameObject)
    self.LoadRequestId = 0
    self.gameObject = nil
    self.isDie = true
    local target = self:GetTarget()
    if target then
        target:UnRegisterOrderChanged(self.UpdateSortingOrder,self)
    end
    Vector3.ReturnToPool(self.offSet)
    Vector3.ReturnToPool(self.pos)
    self.offSet = nil
    self.pos = nil
end
function Buffer:Set(buffId,overlay,targetId,during)
    RedRob.BuffBase.Set(self,buffId,overlay,targetId,during)
    self.cfg = dataTable.getDataTableByStringId("t_buff",buffId)
    if not self.cfg then
        logError("找不到t_buff "..buffId)
        return
    end
    self.showCfg = dataTable.getDataTableByStringId("t_buffshow",buffId)
    if not self.showCfg then
        logError("找不到t_buffshow "..buffId)
        return
    end
    local buffTime = tonumber(self.cfg.f_BuffRound) or 0
    if during == nil then
        self.during = buffTime/1000
    end
    if not string.IsNilOrEmpty(self.cfg.f_BuffSpecialEffect) then
        local list = decodeJsonStrToTabel(self.cfg.f_BuffSpecialEffect)
        for k,v in pairs(list) do
            self.stateList[v] = true
        end
    end
    self:OnBuffStart()
end
--不可被选中
function Buffer:HasUnSelectState()
    return self.stateList[RedRob.Config.BuffState.CAN_NOT_SELECT]
end
function Buffer:GetTarget()
    return RedRob.ActorManager.GetActor(self.targetId)
end
function Buffer:UpdateSortingOrder(order)
    if not self.render then return end
    self.render.sortingOrder = order + RedRob.Config.SortingOrder.buff
end
function Buffer:LoadModel()
    if self.isLoading then
        return
    end
    if string.IsNilOrEmpty(self.showCfg.f_BuffVEXResource) then
        return
    end
    local name = "Prefabs/Skill/"..self.showCfg.f_BuffVEXResource
    self.isLoading = true
    self.resName = name
    self.LoadRequestId = RedRob.PoolMgr.LoadPrefabFromPool(self.resName,self.LoadCallback,self)
end
function Buffer:LoadCallback(go)
    self.gameObject = go
    local target = self:GetTarget()
    if not target then
        self.isDie = true
        return
    end
    self.gameObject.transform:SetParent(target:GetTran(),false)
    Util.Lua_SetLocalPositionXYZ(self.gameObject,0,0,0)
    self.animation = self.gameObject:GetComponentInChildren(TSkeletonAnimation)
    self.render = self.gameObject:GetComponentInChildren(typeof(UnityEngine.Renderer))
    self:UpdateSortingOrder(target:GetSortingOrder())
    self:SetStage(STAGE.start)
    self:SetObjActive(target.isLoaded,true)
    local scale = self.showCfg.f_BuffVEXScale
    if scale > 0 then
        scale = scale / 10000
        Util.Lua_SetLocalScaleXYZ(self.gameObject,scale,scale,scale)
    end
    local p = self.showCfg.f_BuffVEXPosition
    if not string.IsNilOrEmpty(p) and #p > 0 then
        self.pos:Set(tonumber(p[1]),tonumber(p[2]))
        if p[3] then
            local x,y = target:GetBonePos(p[3],true)
            if x then
                self.pos:Set(self.pos.x+x,self.pos.y+y)
            end
        end
        Util.Lua_SetLocalPositionXYZ(self.gameObject,self.pos.x,self.pos.y,0)
    end
    target:RegisterOrderChanged(self.UpdateSortingOrder,self)
end
function Buffer:SetObjActive(active ,forceUpdate)
    if not self.gameObject then return end
    if self.isObjActive ~= active or forceUpdate  then
        self.isObjActive = active
        self.gameObject:SetActive(active)
    end

end
function Buffer:SetStage(stage,forceUpdate)
    local data = self.stageData
    if data.stage == stage and not forceUpdate then
        return
    end
    data.stage = stage
    data.time = 0
    data.countDown = true
    if stage == STAGE.start then
        self:SetAnim(self.showCfg.f_BuffStartName)
        data.maxTime = self.showCfg.f_BuffStarDuration/1000
    elseif stage == STAGE.loop then
        self:SetAnim(self.showCfg.f_BuffLoopName,true)
        data.maxTime = self.during - self.showCfg.f_BuffStarDuration - self.showCfg.f_BuffEndDuration
    elseif stage == STAGE.destroying then
        self:SetAnim(self.showCfg.f_BuffEndName)
        data.maxTime = self.showCfg.f_BuffEndDuration/1000
    end
end
function Buffer:IsDie()
    return self.isDie
end
function Buffer:SetAnim(name,isLoop)
    if not self.animation or string.IsNilOrEmpty(name) then
        return
    end
    isLoop = isLoop or false
    Util.PlayAction(self.animation,name,isLoop)
end
function Buffer:TimeEnd()
    self.isDie = true
end

function Buffer:Update(dt)
    RedRob.BuffBase.Update(self,dt)
    self:UpdateStage(dt)
    self:LoadModel()
    local target = self:GetTarget()
    if target and target.isLoaded then
        self:SetObjActive(true)
    end
end
function Buffer:UpdateStage(dt)
    local data = self.stageData
    if data.maxTime > 0 and data.countDown and data.time < data.maxTime then
        data.time = data.time + dt
        if data.time >= data.maxTime then
            self:SetStage(data.stage + 1)
        end
    end
end
---实例化后，生效前调用(还未加入buff容器中)
function Buffer:OnBuffAwake()

end
---buff生效时
function Buffer:OnBuffStart()
    RedRob.BuffBase.OnBuffStart(self)
end
---相同类型时刷新(更新buff层数、等级、持续时间等)
function Buffer:OnBuffRefresh(overlay)
    self.overlay = overlay
    self.curTime = 0
    self:SetStage(STAGE.loop,true)
end
---当buff销毁前(还未从buff容器中移除)
function Buffer:OnBuffRemove()
    self.isDie = true
end